package fr.asip.cps3.exemple.modele.traitements.fonctionsPKCS11.sessions;

import iaik.pkcs.pkcs11.wrapper.CK_SESSION_INFO;
import iaik.pkcs.pkcs11.wrapper.PKCS11;
import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;

import java.util.LinkedHashMap;

import org.apache.log4j.Logger;

import fr.asip.cps3.exemple.modele.exceptions.ExceptionProgrammeExemple;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionTraitement;
import fr.asip.cps3.exemple.modele.resultats.Resultat;
import fr.asip.cps3.exemple.modele.resultats.ResultatInfo;
import fr.asip.cps3.exemple.modele.traitements.util.TraitementsUtil;

/**
 * Classe de traitement : Obtention d'informations sur la session
 *
 */
public class InfoSession {

	/**
	 * Le loggeur
	 */
	private static Logger log = Logger.getLogger(InfoSession.class);
	
	/**
	 * Renvoie le résultat de l'opération
	 * @param librairie Librairie PKCS#11 à utiliser
	 * @param idSession Identifiant de la session
	 * @return Résultat de l'opération
	 * @throws ExceptionTraitement 
	 */
	public static Resultat traitementP11(PKCS11 librairie, long idSession) throws ExceptionTraitement {
		

		try {
			
			if(librairie != null) {

				ResultatInfo resultat = new ResultatInfo("Obtenir des informations sur la session "+Long.toString(idSession)+" (C_GetSessionInfo)");
				LinkedHashMap<String,String> infos = new LinkedHashMap<String,String>();
				resultat.setInfos(infos);
				
				try {
					
					// Traitement à tester
					CK_SESSION_INFO info = librairie.C_GetSessionInfo(idSession);
		
					// Récupération de l'état de la session
					String etat = "inconnu";
					
					if(info != null) {
						long state = info.state;
						if(state == PKCS11Constants.CKS_RO_PUBLIC_SESSION)
							etat="RO public";
						else if(state == PKCS11Constants.CKS_RO_USER_FUNCTIONS)
							etat="RO utilisateur";
						else if(state == PKCS11Constants.CKS_RW_PUBLIC_SESSION)
							etat="RW public";
						else if(state == PKCS11Constants.CKS_RW_SO_FUNCTIONS)
							etat="RW SO";
						else if(state == PKCS11Constants.CKS_RW_USER_FUNCTIONS)
							etat="RW utilisateur";
					
					
						// Formatage du résultat
						infos.put("Identifiant du slot sur lequel est ouverte la session",Long.toString(info.slotID));
						infos.put("Etat de la session",etat);
						infos.put("Code d'erreur de la carte",Long.toString(info.ulDeviceError));
						infos.put("La session est en lecture seule",(info.flags & PKCS11Constants.CKF_RW_SESSION)!=0?"Non":"Oui");
						infos.put("La session est en lecture/écriture",(info.flags & PKCS11Constants.CKF_RW_SESSION)!=0?"Oui":"Non");
		
					} else {
						
						// Si les informations sont nulles on lève l'exception
						log.error("L'operation a retourne des informations nulles");
						throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_SESSIONS_INFO, "L'opération a retourné des informations nulles");
						
					}			
					
				} catch (PKCS11Exception e) {
					
					log.info("Operation echouee : "+TraitementsUtil.retranscritCodeRetour(e.getErrorCode()));
					resultat.setCodeRetour(e.getErrorCode());
					
				}
				
				return resultat;
				
				
			} else {
				
				// Si la librairie est nulle il est impossible de réaliser l'opération
				log.error("La librairie est nulle");
				throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_SESSIONS_INFO, "La librairie est nulle");
				
			}

		} catch (Throwable t) {
			
			// Si une erreur Traitement a été rencontrée on lève l'exception
			if(t instanceof ExceptionTraitement)
				throw (ExceptionTraitement)t;
			
			// Si une erreur inattendue est survenue la logue et on la lève
			log.error("Une erreur inattendue est survenue : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_SESSIONS_INFO, "Une erreur inattendue est survenue");
			
		}

	}

}
